﻿using System;
using SlimDX.DirectInput;

namespace TileGert
{
  /// <summary>
  /// GertKeyboardInput is a simple keyboard input class that uses DirectInput.
  /// Use the KeyIsPressed and KeyIsReleased methods to check if a key is pressed / released.
  /// The state of the keys is not automatically updated so if you want up-to-date data, you
  /// need to call the Update method. For example you can call Update once every frame of your game.
  /// </summary>
  public class GertKeyboardInput
  {
    private Device<KeyboardState> _keyboard = null;
    private KeyboardState _state = null;
    private GertGame _game = null;
    
    /// <summary>
    /// Creates a new GertKeyboardInput.
    /// </summary>
    public GertKeyboardInput(GertGame game)
    {
      _game = game;
      try
      {
        _keyboard = new Device<KeyboardState>(SystemGuid.Keyboard);
        _keyboard.Acquire();
      }
      catch (Exception ex)
      {
        _game.Logger.LogLine("DirectInput device for the keyboard could not be created: " + ex.Message, 0);
      }
    }
    
    /// <summary>
    /// Lazyly gets the current state of the keyboard with exception handling.
    /// </summary>
    /// <returns>The current keyboard state or null if an exception occurred.</returns>
    private KeyboardState GetKeyboardState()
    {
      if (_state == null)
      {
        try
        {
          _state = _keyboard.GetCurrentState();
        }
        catch (Exception ex)
        {
          _game.Logger.LogLine("Keyboardstate could not be read: " + ex.Message, 1);
          return null;
        }
      }
      return _state;
    }
    
    /// <summary>
    /// Updates the keyboard state that is used by the KeyIsPressed and KeyIsReleased methods.
    /// </summary>
    public void Update()
    {
      _state = null;
    }
    
    /// <summary>
    /// Checks if the given key is pressed in the current state.
    /// </summary>
    /// <param name="key">The key to be checked.</param>
    /// <returns>True if the is pressed, else false.</returns>
    public bool KeyIsPressed(GertKeys key)
    {
      KeyboardState state = GetKeyboardState();
      if (state != null)
        return state.IsPressed((Key)key);
      else
        return false;
    }
    
    /// <summary>
    /// Checks if the given key is pressed in the current state.
    /// </summary>
    /// <param name="key">The key to be checked.</param>
    /// <returns>True if the is pressed, else false.</returns>
    public bool KeyIsReleased(GertKeys key)
    {
      KeyboardState state = GetKeyboardState();
      if (state != null)
        return state.IsReleased((Key)key);
      else
        return false;
    }
    
    /// <summary>
    /// Gets the name of the keyboard for display purposes.
    /// </summary>
    public string DisplayName
    {
      get { return _keyboard.DeviceInformation.ProductName; }
    }
    
  }
}
